package user

import (
	_"crypto/md5"
	_"encoding/hex"
	"encoding/json"
	"fmt"
	"GoServer/database"
	"GoServer/ratelimit"
	"sync"
	"time"
	"github.com/satori/go.uuid"
	"github.com/name5566/leaf/gate"
)

type UserCacheInfo struct {
	UserName string
	Auths    string
	Angets   gate.Agent
	Lb       *ratelimit.LeakyBucket //水桶对象（限流使用）
	Angetstr string
}

type Setloginchannel struct {
	Playerid  uint   `json:"Playerid"`
	Username  string `json:"UserName"`
	Logintime int64  `json:"SendTime"` //登录时间
	Gateid    string `json:"Sender"`   //网关id
}

var g_userInfoLock sync.Mutex
var g_mapUserInfo map[string]*UserCacheInfo
var g_mapUserInfo_new map[gate.Agent]string
var g_user map[string]*database.Authuser

func Md5V() string  {
	// return fmt.Sprintf("%s", uuid.Must(uuid.NewV4()))
	u1 := uuid.Must(uuid.NewV4())
	uuid := fmt.Sprintf("%s",u1)
	return uuid
}


func AdminQueryInit(Username string, Authkey string, Anget string) (bool, string) {
	var Userall database.Authuser
	//缓存中获取
	getCache :=  UserInfoTableCacheGet(Authkey)
	output := ""
	if getCache != nil {
		Userall = *getCache
		fmt.Println("缓存中获取数据")
		fmt.Println(Userall)
	} else {
		sql := fmt.Sprintf("SELECT * FROM user where username = '%v' and password_reset_token = '%v'", Username, Authkey)
		fmt.Println(sql)
		DbclientFishAll := database.DbclientFishAll
		err := DbclientFishAll.Raw(sql).Scan(&Userall).Error
		if err != nil || Userall.Username == "" {
			fmt.Println(err.Error())
			return false, output
		}
		UserInfoTableCacheAdd(Userall)
	}
	fmt.Println(Username)
	//写入登录loginchanel

	g_JsonConfig := database.G_JsonConfig
	ToserverTopic := g_JsonConfig.PrivatetopicAll.Gategetserver
	mapMsg := make(map[string]interface{})
	m := make(map[string]interface{})

	m["PlayerID"] = Userall.Id
	m["Nickname"] = Userall.Nickname
	m["Avatarurl"] = Userall.Avatarurl
	m["userName"] = Userall.Username
	m["source"] = Userall.Source
	// mapMsg["userName"] = Userall.Username
	mapMsg["userName"] = Anget
	mapMsg["SendTime"] = time.Now().Unix()
	mapMsg["Sender"] = ToserverTopic
	mapMsg["MsgData"] = m
	mapMsg["Anget"] =  Anget
	b, err := json.Marshal(&mapMsg)
	// b, err := json.Marshal(Setloginchanneldata)
	if err != nil {
		fmt.Println("setloginchannel error")
		return false, output
	} else {
		outputOk := string(b)

		return true, outputOk
	}

}

// 初始化用户缓存
func UserInfoCacheInit() {
	g_mapUserInfo = make(map[string]*UserCacheInfo)
	g_mapUserInfo_new = make(map[gate.Agent]string)
	g_user = make(map[string]*database.Authuser)
	// 启动检查过期缓存
	go userInfoDoCheck()
}

//缓存信息组装
func UserDaoGetUserInfoWithAuth(userName string, Auth string, Anget gate.Agent, Angetstr string) (UserCacheInfo, error) {
	var users UserCacheInfo
	users.UserName = userName
	users.Auths = Auth
	users.Angets = Anget
	users.Angetstr = Angetstr
	lb := ratelimit.NewLeakyBucket(time.Second, 30)
	users.Lb = lb
	return users, nil
}

//增加在线用户缓存
func UserInfoCacheAdd(info UserCacheInfo) {
	// fmt.Println(info.UserName)
	newItem := new(UserCacheInfo)
	*newItem = info
	g_userInfoLock.Lock()
	g_mapUserInfo[info.Angetstr] = newItem
	g_mapUserInfo_new[info.Angets] = info.Angetstr
	g_userInfoLock.Unlock()
}

//清除用户缓存
func UserInfoCacheDELETE(Angetstr string) {
	g_userInfoLock.Lock()
	delete(g_mapUserInfo, Angetstr)
	g_userInfoLock.Unlock()
}

//获取用户信息缓存
func UserInfoCacheGet(Angetstr string) *UserCacheInfo {
	g_userInfoLock.Lock()
	ret, ok := g_mapUserInfo[Angetstr]
	g_userInfoLock.Unlock()

	if ok {
		// ret.AddTime = time.Now()
		return ret
	} else {
		return nil
	}
}

//获取连接对应User
func GetSocketUser(Anget gate.Agent) string{
	g_userInfoLock.Lock()
	ret, ok := g_mapUserInfo_new[Anget]
	g_userInfoLock.Unlock()
	if ok {
		return ret
	} else {
		return ""
	}
}

//删除连接缓存信息
func DelSocketUser(Anget gate.Agent){
	g_userInfoLock.Lock()
	delete(g_mapUserInfo_new, Anget)
	g_userInfoLock.Unlock()
}

//用户数据信息缓存
func  UserInfoTableCacheAdd(info database.Authuser) {
	newItem := new(database.Authuser)
	*newItem = info
	g_userInfoLock.Lock()
	g_user[info.Authkey] = newItem
	g_userInfoLock.Unlock()
}
//获取用户数据缓存
func UserInfoTableCacheGet(Authkey string) *database.Authuser {
	g_userInfoLock.Lock()
	ret, ok := g_user[Authkey]
	g_userInfoLock.Unlock()
	if ok {
		return ret
	} else {
		return nil
	}
}

//检查过期缓存
func userInfoDoCheck() {
	for {
		g_userInfoLock.Lock()
		for _, cacheInfo := range g_user {
			if time.Now().Unix() > cacheInfo.Expire_at {
				delete(g_user, cacheInfo.Authkey)
			}
		}
		g_userInfoLock.Unlock()

		time.Sleep(time.Second * 30)
	}
}
